$(function() {

	$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
		options.url = conquest.static.restPath + options.url + '?language=' + conquest.static.language;
	});

	var MemberGroupsView = Backbone.View.extend({
		el: '.mg-container',
		render: function(members) {
			var view = this;
			if (_.isUndefined(view.groupKey)) {
				view.groupKey = 'typeDisplay';
			}
			if (_.isUndefined(view.sortKey)) {
				view.sortKey = 'name';
			}

			var groups = conquest.util.membersGroupBy(members, view.groupKey, view.sortKey);

			view.$el.html(Handlebars.templates['members-groups.hbs']({
				membersGroups: groups
			}));

			view.$el.find('.mg-control-group label[data-group-key="' + view.groupKey + '"]').addClass('active');
			view.$el.find('.mg-control-group label').click(function() {
				$(this).addClass('active').siblings().removeClass('active');
				view.groupKey = $(this).data('group-key');
				view.render(members);
			});
			view.$el.find('.mg-control-sort label[data-sort-key="' + view.sortKey + '"]').addClass('active');
			view.$el.find('.mg-control-sort label').click(function() {
				$(this).addClass('active').siblings().removeClass('active');
				view.sortKey = $(this).data('sort-key');
				view.render(members);
			});

			view.$el.find('a[data-image-base]').popover({
				html: true,
				trigger: 'hover',
				content: function() {
					return conquest.util.writeCardImgElem($(this).data('image-base'), {
						class: 'card-md'
					});
				}
			});
		}
	});

	var ViewBase = Backbone.View.extend({
		el: '.content',
		events: {
			'click a': 'linkClick'
		},
		linkClick: function(e) {
			var root = conquest.static.root;
			var href = $(e.currentTarget).attr('href');
			if (href && href.indexOf(root) == 0) {
				e.preventDefault();
				conquest.router.navigate(href.replace(conquest.static.root, ''), {
					trigger: true
				});
			}
		},
		renderMessages: function(options) {
			if (this.messages) {
				var $template = $(Handlebars.templates['global-messages.hbs']({
					messages: this.messages
				}));
				delete this.messages;
				this.$el.prepend($template);
				setTimeout(function() {
					$template.fadeOut("slow");
				}, 2000);
			}
		}
	});

	var DecksView = ViewBase.extend({
		render: function() {
			var template = Handlebars.templates['deck-list.hbs']({
				decks: conquest.util.toJSON(conquest.getDecks().models)
			});
			this.$el.html(template);
			this.$el.find('.actions-container').append(
				Handlebars.templates['deck-actions.hbs']({
					actions: {
						decknew: {
							showText: true
						}
					}
				}));
			this.renderMessages();
		}
	});
	var decksView = new DecksView();

	var DeckView = ViewBase.extend({
		render: function(id) {
			var view = this;
			this.deck = new Deck({
				id: id
			});
			this.deck.fetch({
				success: function() {
					var deckId = view.deck.get('id');
					var deckTechName = view.deck.get('techName');
					var template = Handlebars.templates['deck-view.hbs']({
						deck: view.deck.toJSON()
					});
					view.$el.html(template);
					var actionsTemplate = Handlebars.templates['deck-actions.hbs']({
						actions: {
							decknew: {},
							deckexport: {},
							deckedit: _.isNumber(deckId) ? {
								id: deckId,
								techName: deckTechName
							} : undefined,
							decklist: true,
						}
					});
					view.$el.find('.actions-container').append(actionsTemplate);

					view.groupsView = new MemberGroupsView({
						el: '.mg-container'
					});
					view.groupsView.render(view.deck.get('members'));
				}
			});
		}
	});

	var MembersListView = Backbone.View.extend({
		el: '.members-list-container',
		render: function(members, options) {
			var layout = options.layout;
			var templateName = undefined;
			if (layout === 'grid-2') {
				templateName = 'deck-members-grid-2.hbs';
			} else if (layout === 'grid-3') {
				templateName = 'deck-members-grid-3.hbs';
			} else if (layout === 'grid-4') {
				templateName = 'deck-members-grid-4.hbs';
			} else if (layout === 'grid-6') {
				templateName = 'deck-members-grid-6.hbs';
			} else {
				// list layout is the default
				templateName = 'deck-members-list.hbs';
			}

			var template = Handlebars.templates[templateName]({
				members: members.toJSON()
			});
			this.$el.html(template);

			var $members = this.$el
				.find('.members-grid-item, .members-list-item');
			$members.each(function() {
				var $member = $(this);
				var $buttons = $member.find('.btn-group-qty .btn');
				var member = members.models[$members.index($member)];
				var $active = $buttons.eq(member.get('quantity')).addClass('active');
				if (member.get('fixedQuantity') === true) {
					$active.siblings().attr('disabled', 'disabled');
				}

				$buttons.click(function() {
					var $button = $(this);
					$button.addClass('active').siblings().removeClass('active');
					member.set({
						quantity: parseInt($button.text())
					});
				});
			});

			this.$el.find('[data-toggle="tooltip"]').tooltip({
				container: 'body'
			});
			this.$el.find('a[data-image-base]').popover({
				html: true,
				trigger: 'hover',
				content: function() {
					return conquest.util.writeCardImgElem($(this).data(
						'image-base'), {
						class: 'card-md'
					});
				}
			});
		}
	});

	var DeckCreateView = ViewBase.extend({
		render: function() {
			var warlords = _.where(conquest.dict.cards, {
				type: 'warlord'
			});
			var template = Handlebars.templates['deck-create.hbs']({
				warlords: warlords
			});
			this.$el.html(template);
			this.$el.find('.actions-container').append(
				Handlebars.templates['deck-actions.hbs']({
					actions: {
						decklist: {
							showText: true
						}
					}
				}));

			var view = this;
			$('tbody tr').mouseenter(
				function() {
					var $this = $(this).addClass('highlight');;
					var imgElem = conquest.util.writeCardImgElem($this
						.data('card-image-base'));
					view.$el.find('.card-container').empty()
						.append(imgElem);
				}).mouseleave(function() {
				$(this).removeClass('highlight');
				view.$el.find('.card-container').empty();
			});
		}
	});

	var DeckEditView = ViewBase.extend({
		config: new Backbone.Model({
			layout: 'list',
			filter: new Backbone.Model()
		}),
		updateTotals: function() {
			var quantity = this.deck.computeTotalQuantity();
			var cost = this.deck.computeTotalCost();
			this.$el.find('#deckTotalQuantity').text(quantity);
			this.$el.find('#deckTotalCost').text(cost);
		},
		render: function(options) {
			var view = this;
			var renderInternal = function() {
				var filter = {
					factions: conquest.getValidDeckFactions(view.deck.get('warlord').faction),
					types: [{
						code: 'army',
						message: 'type.army',
						messageShort: 'type.army.sh'
					}, {
						code: 'attachment',
						message: 'type.attachment',
						messageShort: 'type.attachment.sh'
					}, {
						code: 'event',
						message: 'type.event',
						messageShort: 'type.event.sh'
					}, {
						code: 'support',
						message: 'type.support',
						messageShort: 'type.support.sh'
					}]
				};

				var template = Handlebars.templates['deck-edit.hbs']({
					deck: view.deck.toJSON(),
					filter: filter
				});
				view.$el.html(template);
				view.updateTotals();
				view.renderMessages();

				var deckId = view.deck.get('id');
				var deckTechName = view.deck.get('techName');
				view.$el.find('.actions-container').append(
					Handlebars.templates['deck-actions.hbs']({
						actions: {
							decknew: {},
							deckexport: {},
							deckview: _.isNumber(deckId) ? {
								id: deckId,
								techName: deckTechName
							} : undefined,
							decksave: {},
							deckdelete: _.isNumber(deckId) ? {} : undefined,
							decklist: {},
						}
					}));

				var filter = function() {
					var factions = $('.btn-group.btn-group-filter.filter-faction > .btn.active').map(function() {
						return $(this).data('faction');
					}).get();
					var types = $('.btn-group.btn-group-filter.filter-type > .btn.active').map(function() {
						return $(this).data('type');
					}).get();
					var sets = view.config.get('filter').get('sets');

					var cardName;
					var cardTrait;
					var cardKeyword;
					if (view.searchbar) {
						var suggestion = view.searchbar.suggestion;
						var dataset = view.searchbar.dataset;
						var text = view.searchbar.text;
						if (suggestion && dataset) {
							if (dataset == 'cards') {
								cardName = suggestion.name;
							} else if (dataset == 'traits') {
								cardTrait = suggestion.description;
							} else if (dataset == 'keywords') {
								cardKeyword = suggestion.description;
							}
						}
					}

					var filteredMembers = view.deck.get('members').filter(
						function(member) {
							var card = member.get('card');
							var matches = factions.indexOf(card.faction) > -1 && types.indexOf(card.type) > -1 && sets.indexOf(card.setTechName) > -1
							if (cardName) {
								matches = matches && card.name == cardName;
							} else if (cardTrait) {
								matches = matches && card.trait && card.trait.indexOf(cardTrait) > -1;
							} else if (cardKeyword) {
								matches = matches && card.keyword && card.keyword.indexOf(cardKeyword) > -1;
							} else if (text) {
								text = text.toLowerCase();
								matches = matches && (card.name.toLowerCase().indexOf(text) > -1 || card.trait && card.trait.toLowerCase().indexOf(text) > -1 || card.keyword && card.keyword.toLowerCase().indexOf(text) > -1);
							}
							return matches;
						});

					view.deck.get('filteredMembers').reset(
						filteredMembers);
				};

				view.config.get('filter').set({
					sets: _.pluck(_.where(conquest.dict.sets, {
						released: true
					}), 'techName')
				});

				view.membersListView = new MembersListView({
					el: '.members-list-container'
				});
				view.membersListView.listenTo(view.deck.get('filteredMembers'), 'reset', function(filteredMembers) {
					this.render(filteredMembers, {
						layout: view.config.get('layout')
					});
				});

				view.groupsView = new MemberGroupsView({
					el: '.mg-container'
				});
				view.deck.get('members').each(
					function(member) {
						view.listenTo(member, 'change:quantity', function(member, quantity, options) {
							if (options.batchChange !== true) {
								view.groupsView.render(member.collection);
								view.updateTotals();
							}
						});
					});
				view.listenTo(view.deck, 'invalid', function(deck) {
					view.messages = [{
						kind: 'danger',
						title: 'core.error',
						message: deck.validationError
					}];
					view.renderMessages();
				});
				view.listenTo(view.config, 'change:layout', function(config) {
					view.membersListView.render(view.deck.get('filteredMembers'), {
						layout: config.get('layout')
					});
				});
				view.listenTo(view.deck, 'change:configCsQuantity',
					function(deck) {
						deck.adjustQuantities();
						view.membersListView.render(view.deck.get('filteredMembers'), {
							layout: view.config.get('layout')
						});
						view.groupsView.render(view.deck.get('members'));
						view.updateTotals();
					});
				view.listenTo(view.config, 'change:filter', function(config) {
					filter();
				});

				$('.btn-group.btn-group-filter > .btn').click(function(event) {
					var $this = $(this);
					if (event.ctrlKey) {
						$this.addClass('active').siblings().removeClass('active');		
					} else {
						$this.toggleClass('active');
					}
					
					filter();
				});

				$('.btn-group.btn-group-layout > .btn').click(function() {
					var $this = $(this);
					$this.addClass('active').siblings()
						.removeClass('active');
					view.config.set({
						layout: $this.data('layout')
					});
				});

				var layout = view.config.get('layout');
				$('.btn-group.btn-group-layout > .btn[data-layout="' + layout + '"]').addClass('active');

				//
				// save deck
				//
				$('#deckSave').click(function() {
					var values = {
						name: view.$el.find('#deckName').val().trim(),
						description: view.$el.find('#deckDescription').val().trim()
					};
					view.deck.save(values, {
						success: function(model, response, options) {
							console.info("Save success");
							conquest.saveDeck(model);
							conquest.router.navigate('edit/' + model.get('id') + '-' + model.get('techName'));
							view.deck = model;
							view.messages = [{
								kind: 'success',
								title: 'core.ok',
								message: 'core.deck.save.success'
							}];
							view.render();
						},
						error: function(model, response, options) {
							console.info("Save error");
							view.messages = [{
								kind: 'danger',
								title: 'core.error',
								message: 'core.deck.save.error',
								context: response.responseJSON.timestamp ? ('timestamp: ' + response.responseJSON.timestamp) : undefined
							}];
							view.renderMessages();
						}
					});
				});

				//
				// delete deck
				//
				$('#deckDelete').click(function() {
					view.deck.destroy({
						success: function(model, response, options) {
							console.info("Delete success");
							conquest.deleteDeck(model);
							conquest.router.navigate('');
							decksView.messages = [{
								kind: 'success',
								title: 'core.ok',
								message: 'core.deck.delete.success'
							}];
							decksView.render();
						},
						error: function(model, response, options) {
							console.info("Delete error");
							view.messages = [{
								kind: 'danger',
								title: 'core.error',
								message: 'core.deck.delete.error',
								context: response.responseJSON.timestamp ? ('timestamp: ' + response.responseJSON.timestamp) : undefined
							}];
							view.renderMessages();
						}
					});
				});

				//
				// export deck
				//
				var $exportModal = $(Handlebars.templates['deck-export.hbs']());
				$exportModal.find('a').click(function(e) {
					e.preventDefault();
					$(this).tab('show');
				});
				$('#deckExport').click(function() {
					var GK = 'group-key';
					var SK = 'sort-key';
					$exportModal.data(GK, $exportModal.data(GK) || 'typeDisplay');
					$exportModal.data(SK, $exportModal.data(SK) || 'name');

					var renderData = function() {
						var membersGroups = conquest.util.membersGroupBy(view.deck.get('members'), $exportModal.data(GK), $exportModal.data(SK));
						var plainData = Handlebars.templates['deck-export-plain.hbs']({
							warlord: view.deck.get('warlord'),
							membersGroups: membersGroups
						});
						$exportModal.find('#exportPlain textarea').val(plainData);
						var bbCodeData = Handlebars.templates['deck-export-bbcode.hbs']({
							warlord: view.deck.get('warlord'),
							membersGroups: membersGroups
						});
						$exportModal.find('#exportBBCode textarea').val(bbCodeData);
					};

					$exportModal.find('.mg-control-group label[data-group-key="' + $exportModal.data(GK) + '"]').addClass('active');
					$exportModal.find('.mg-control-group label').click(function() {
						$(this).addClass('active').siblings().removeClass('active');
						$exportModal.data(GK, $(this).data(GK));
						renderData();
					});
					$exportModal.find('.mg-control-sort label[data-sort-key="' + $exportModal.data(SK) + '"]').addClass('active');
					$exportModal.find('.mg-control-sort label').click(function() {
						$(this).addClass('active').siblings().removeClass('active');
						$exportModal.data(SK, $(this).data(SK));
						renderData();
					});

					var client = new ZeroClipboard($exportModal.find('#exportCopyAndCloseButton')[0]);

					client.on('ready', function(readyEvent) {
						client.on('copy', function(event) {
							var clipboard = event.clipboardData;
							clipboard.setData('text/plain', $('.tab-pane.active textarea').val());
						});
					});

					renderData();
					$exportModal.modal();
				});

				//
				// tooltips
				//
				// view.$el.find('.members-list-filter-container
				// [data-toggle="tooltip"]').tooltip({container:
				// 'body'});
				view.$el.find('[data-toggle="tooltip"]').tooltip({
					container: 'body',
					trigger: 'hover click'
				});

				//
				// config popover
				//				
				var $configTrigger = view.$el.find('#configTrigger').popover({
					html: true,
					trigger: 'click focus',
					placement: 'bottom',
					animation: false,
					title: conquest.static.messages['core.settings'],
					content: Handlebars.templates['deck-config.hbs']({})
				});

				$configTrigger.on('shown.bs.popover', function() {
					var $configContent = view.$el.find('#configContent');
					var $configCsQuantityRadios = $configContent.find('input[name="csQuantity"]');
					$configCsQuantityRadios.filter('[value="' + view.deck.get('configCsQuantity') + '"]').prop('checked', true);
					$configContent.find('#configApply').click(function() {
						$configTrigger.popover('hide');
						view.deck.set({
							configCsQuantity: parseInt($configCsQuantityRadios.filter(':checked').val())
						});
					});
					$configContent.find('#configCancel').click(function() {
						$configTrigger.popover('hide');
					});
				});

				//
				// filter popover
				//
				var filterContent = Handlebars.templates['deck-filter.hbs']({
					tree: conquest.getSetTree()
				});
				var $filterTrigger = view.$el.find('#filterTrigger').popover({
					html: true,
					trigger: 'click focus',
					placement: 'bottom',
					animation: false,
					title: conquest.static.messages['core.filters'],
					content: filterContent
				});

				$filterTrigger.on('shown.bs.popover', function() {
					var sets = view.config.get('filter').get('sets');
					var cycles = view.config.get('filter').get('cycles');
					var $filterContent = view.$el.find('#filterContent');
					var $sets = $filterContent.find('li:not(:has(ul)) input[type="checkbox"]');
					var $cycles = $filterContent.find('li:has(ul) > input[type="checkbox"]');
					$sets.each(function() {
						var $this = $(this);
						$this.prop('checked', sets && sets.indexOf($this.val()) > -1);
					});
					$cycles.each(function() {
						var $this = $(this);
						$this.prop('checked', cycles && cycles.indexOf($this.val()) > -1);
						$this.click(function() {
							$this.siblings().filter('ul').find('input[type="checkbox"]').prop('checked', $this.prop('checked'));
						});
					});
					$filterContent.find('#filterApply').click(function() {
						$filterTrigger.popover('hide');
						var sets = [];
						$sets.filter(':checked').each(function() {
							sets.push($(this).val());
						});
						var cycles = [];
						$cycles.filter(':checked').each(function() {
							cycles.push($(this).val());
						});
						view.config.get('filter').set({
							sets: sets
						});
						view.config.get('filter').set({
							cycles: cycles
						});
						view.config.trigger('change:filter', view.config);
					});
					$filterContent.find('#filterCancel').click(function() {
						$filterTrigger.popover('hide');
					});
				});

				//
				// search
				//

				// constructs the suggestion engine
				var cards = new Bloodhound({
					datumTokenizer: Bloodhound.tokenizers.obj
						.whitespace('name'),
					queryTokenizer: Bloodhound.tokenizers.whitespace,
					local: $.map(view.deck.get('members').toJSON(),
						function(member) {
							return {
								name: member.card.name,
								card: member.card
							};
						})
				});

				var traits = new Bloodhound({
					datumTokenizer: Bloodhound.tokenizers.obj
						.whitespace('description'),
					queryTokenizer: Bloodhound.tokenizers.whitespace,
					local: conquest.dict.traits
				});

				var keywords = new Bloodhound({
					datumTokenizer: Bloodhound.tokenizers.obj
						.whitespace('description'),
					queryTokenizer: Bloodhound.tokenizers.whitespace,
					local: conquest.dict.keywords
				});

				cards.initialize();
				traits.initialize();
				keywords.initialize();

				var $typeahead = $('#search').typeahead({
					hint: true,
					highlight: true,
					minLength: 1
				}, {
					name: 'cards',
					displayKey: 'name',
					source: cards.ttAdapter(),
					templates: {
						suggestion: Handlebars
							.compile('{{name}}&nbsp;<span class="tt-no-highlight">{{card.setName}} | {{card.factionDisplay}} | {{card.typeDisplay}} | {{card.trait}}</span>'),
						header: '<div class="tt-multi-header">' + conquest.static.messages['core.card'] + '</div>'
					}
				}, {
					name: 'traits',
					displayKey: 'description',
					source: traits.ttAdapter(),
					templates: {
						header: '<div class="tt-multi-header">' + conquest.static.messages['core.trait'] + '</div>'
					}
				}, {
					name: 'keywords',
					displayKey: 'description',
					source: keywords.ttAdapter(),
					templates: {
						header: '<div class="tt-multi-header">' + conquest.static.messages['core.keyword'] + '</div>'
					}
				});

				$typeahead.on('typeahead:selected', function($event, suggestion, dataset) {
					console.log('selected' + $event);
					view.searchbar = {
						suggestion: suggestion,
						dataset: dataset
					};
				}).on('typeahead:autocompleted', function($event, suggestion, dataset) {
					console.log('autocompleted' + $event);
					view.searchbar = {
						suggestion: suggestion,
						dataset: dataset
					};
				}).on('typeahead:closed', function($event) {
					// console.log('closed');
					view.searchbar.text = $('#search')
						.typeahead('val');
				}).on('typeahead:opened', function($event) {
					// console.log('opened');
					view.searchbar = {};
				}).on('keyup', function($event) {
					// console.log('keyup');
					if ($event.keyCode == 13) {
						$('#search').typeahead('close');
						filter();
					}
				});

				//
				// sliders
				//
				// $('.slider').slider({});
				$('.slider').each(function() {
					var $this = $(this);
					$this.slider({
						range: true,
						min: $this.data('slider-min'),
						max: $this.data('slider-max'),
						// values: [ $this.data('slider-min'), $this.data('slider-max') ]
						values: [ 1, 3 ]
					});
				});

				view.groupsView.render(view.deck.get('members'));
				filter();
			};

			if (_.isUndefined(options)) {
				renderInternal();
			} else {
				if (_.isNumber(options.deckId)) {
					var view = this;
					this.deck = new Deck({
						id: options.deckId
					});
					this.deck.fetch({
						success: function() {
							conquest.saveDeck(view.deck);
							renderInternal();
						}
					});
				} else if (_.isNumber(options.warlordId)) {
					this.deck = new Deck({
						warlordId: options.warlordId,
						members: conquest
							.getValidDeckMembers(options.warlordId),
						configCsQuantity: 1
					}, {
						parse: true
					});
					renderInternal();
				} else {
					renderInternal();
				}
			}
		}
	});

	var Router = Backbone.Router.extend({
		routes: {
			'new': 'createNewDeck',
			'new/:id': 'editNewDeck',
			'edit/:id': 'editDeck',
			':id': 'viewDeck',
			'': 'viewDecks',
		}
	});

	conquest.router = new Router();
	conquest.router.on('route:createNewDeck', function() {
		var deckCreateView = new DeckCreateView();
		deckCreateView.render();
	}).on('route:editNewDeck', function(id) {
		var deckEditView = new DeckEditView();
		deckEditView.render({
			warlordId: parseInt(id)
		});
	}).on('route:editDeck', function(id) {
		var deckEditView = new DeckEditView();
		deckEditView.render({
			deckId: parseInt(id)
		});
	}).on('route:viewDecks', function() {
		decksView.render();
	}).on('route:viewDeck', function(id) {
		var deckView = new DeckView();
		deckView.render(parseInt(id));
	});

	conquest.static.root = '/' + conquest.static.language + '/deck/';

	Backbone.history.start({
		pushState: true,
		root: conquest.static.root
	});
	// Backbone.history.start();
});